﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Reviewed

#pragma once
#include "Vector3d.h"
#include "Intervald.h"
#include "DiscretizeData.h"
#include "GcmpApiDeclaration.h"
#include "DiscreteEpsilonType.h"

namespace gcmp
{
    class ICurve2d;
    class ICurve3d;
    class IEdge;
    class IFace;
    class ISurface;
    class IBody;
    class IPolyCurve;
    class IPolyCurve3d;

    class IDiscretize
    {
    public:
        virtual ~IDiscretize() { }

        /// \brief 设置是否使用Delaunay(狄洛尼)三角剖分算法，默认为false
        /// \param isUseDelaunay  是否使用Delaunay算法
        /// \return
        /// \note 开启后不保证一直离散要求，即重合的两个圆面，离散出来的顶点不一定重合；
        ///       对复杂的面（多个洞或边很多）性能会提升很多 
        virtual void SetIsUseDelaunayTriangulation(bool isUseDelaunay) = 0;

        /// \brief  把二维曲线离散成点集
        /// \param  const ICurve2d* pGmICurve2d                二维曲线
        /// \param  double dDistanceEpsilon                    距离精度
        /// \param  double dAngleEpsilon                       角度精度
        /// \param  std::vector<Vector2d> &discretePoints      离散成的点集
        /// \return bool 成功返回true，失败返回false
        virtual bool Discretize(const ICurve2d* pGmICurve2d, double dDistanceEpsilon, double dAngleEpsilon, std::vector<Vector2d> &discretePoints) const = 0;

        /// \brief  把三维曲线离散成点集
        /// \param const ICurve3d* pGmICurve3d                三维曲线
        /// \param double dDistanceEpsilon                    距离精度
        /// \param double dAngleEpsilon                       角度精度
        /// \param std::vector<Vector3d> &discretePoints      离散成的点集
        /// \return bool 成功返回true，失败返回false
        virtual bool Discretize(const ICurve3d* pGmICurve3d, double dDistanceEpsilon, double dAngleEpsilon, std::vector<Vector3d> &discretePoints) const = 0;

        /// \brief  把拓扑边离散成点集
        /// \param const IEdge* pGmEdge                        拓扑边
        /// \param double dDistanceEpsilon                     距离精度
        /// \param double dAngleEpsilon                        角度精度
        /// \param std::vector<Vector3d> &discretePoints       离散成的点集
        /// \return bool 成功返回true，失败返回false
        virtual bool Discretize(const IEdge* pGmEdge, double dDistanceEpsilon, double dAngleEpsilon, std::vector<Vector3d> &discretePoints) const = 0;

           
        /// \brief  将拓扑面离散成三角面片(不带索引)
        /// \param  const IFace* pGmFace                         拓扑面
        /// \param double dDistanceEpsilon                       距离精度
        /// \param double dAngleEpsilon                          角度精度
        /// \param  const double dZValue                         水平拓扑面的 Z 坐标
        /// \param std::vector<Vector3d> &points                 离散成的点集，三个点构成一个三角片
        /// \param std::vector<Vector3d> &normals                点集对应的法向
        /// \param std::vector<Vector2d>*  pParameterUVs         离散点在原来曲面上的参数,当输入为 nullptr 时不输出
        /// \return bool 成功返回true，失败返回false
        virtual bool Discretize(const IFace* pGmFace, double dDistanceEpsilon, double dAngleEpsilon, const double dZValue, std::vector<Vector3d> &points,
            std::vector<Vector3d> &normals, std::vector<Vector2d>* pParameterUVs) const = 0;

        /// \brief  将拓扑面离散成三角面片(带索引)
        /// \param  const IFace* pGmFace                          拓扑面
        /// \param double dDistanceEpsilon                        距离精度
        /// \param double dAngleEpsilon                           角度精度
        /// \param  const double dZValue                          水平拓扑面的 Z 坐标（标高）
        /// \param std::vector<Vector3d> &vertexPoints            离散成的点集
        /// \param std::vector<Vector3d> &normals                 点集对应的法向
        /// \param std::vector<int> &triangleIndexs               顶点索引，每三个 vertexPoints 点一组作为三角片
        /// \param std::vector<int> *const pLineIndexs            顶点索引，每两个 vertexPoints 点作为线段，当输入为 nullptr 时不输出折线段
        /// \param std::vector<Vector2d>* const pParameterUVs     离散点在原来曲面上的参数,当输入为 nullptr 时不输出
        /// \return bool 成功返回true，失败返回false
        virtual bool Discretize(const IFace* pGmFace, double dDistanceEpsilon, double dAngleEpsilon, const double dZValue, std::vector<Vector3d> &vertexPoints,
            std::vector<Vector3d> &normals, std::vector<int> &triangleIndexs, std::vector<int>* pLineIndexs, std::vector<Vector2d>* pParameterUVs) const = 0;

        
        /// \brief  把曲面离散成索引形式的三角面片(带索引)
        /// \param  const ISurface *pGmISurface                       曲面
        /// \param double dDistanceEpsilon                            距离精度
        /// \param double dAngleEpsilon                               角度精度
        /// \param std::vector<Vector3d> &points                      离散成的点集
        /// \param std::vector<Vector3d> &normals                     点集对应的法向
        /// \param std::vector<int> &triangleIndexs                   三角面片链表（存三个顶点的索引）
        /// \param std::vector<Vector2d> * pParameterUVs              离散点在原来曲面上的参数,当输入为 nullptr 时不输出
        /// \return bool 成功返回true，失败返回false
        virtual bool Discretize(const ISurface *pGmISurface, double dDistanceEpsilon, double dAngleEpsilon, std::vector<Vector3d> &points,
            std::vector<Vector3d> &normals, std::vector<int> &triangleIndexs, std::vector<Vector2d>* pParameterUVs) const = 0;


        /// \brief  把体离散成索引形式的三角面片(带索引)
        /// \param  const IBody *pGmIBody                                  体
        /// \param  double dDistanceEpsilon                                距离精度
        /// \param  double dAngleEpsilon                                   角度精度
        /// \param std::vector<Vector3d> &points                           离散成的点集
        /// \param std::vector<Vector3d> &normals                          在原来曲面上的法向
        /// \param std::vector<int> &triangleIndexs                        三角面片链表（存三个顶点在pointList中的索引，每三个索引构成一个三角形）
        /// \param std::vector<Vector2d> * pParameterUVs                   离散点在原来曲面上的参数,当输入为 nullptr 时不输出
        /// \param std::vector<Vector3d> * pEdgePoints                     离散边的点集
        /// \param std::vector<int> * pEdgeIndexs                          离散边的点索引(两个顶点在pEdgePoints中的索引，构成一个线段)
        /// \param std::vector<int> * pFaceToTriangleNum                   每个面对应离散后的三角面片数，面的顺序与体中面的顺序一致
        /// \param std::vector<int> * pEdgeToLineNum                       每条边对应离散后的线段数，边的顺序与体中边的顺序一致
        /// \param DiscreteEpsilonType deType                            几何离散的容差给定方式
        /// \return bool 成功返回true，失败返回false
        virtual bool Discretize(
            const IBody *pGmIBody,
            double dDistanceEpsilon,
            double dAngleEpsilon,
            std::vector<Vector3d> &points,
            std::vector<Vector3d> &normals,
            std::vector<int> &triangleIndexs,
            std::vector<Vector2d> *pParameterUVs,
            std::vector<Vector3d> *pEdgePoints,
            std::vector<int> *pEdgeIndexs,
            std::vector<int> *pFaceToTriangleNum,
            std::vector<int> *pEdgeToLineNum,
            DiscreteEpsilonType deType) const = 0;

        /// \brief  把体离散成索引形式的三角面片(带索引)  和Discretize不同的是，此版本的points  normals  pParameterUVs size相同, points可能有重复
        /// \param  const IBody *pGmIBody                                  体
        /// \param  double dDistanceEpsilon                                距离精度
        /// \param  double dAngleEpsilon                                   角度精度
        /// \param std::vector<Vector3d> &points                           离散成的点集   
        /// \param std::vector<Vector3d> &normals                          在原来曲面上的法向
        /// \param std::vector<int> &triangleIndexs                        三角面片链表（存三个顶点在pointList中的索引，每三个索引构成一个三角形）
        /// \param std::vector<Vector2d> * pParameterUVs                   离散点在原来曲面上的参数,当输入为 nullptr 时不输出
        /// \param std::vector<Vector3d> * pEdgePoints                     离散边的点集
        /// \param std::vector<int> * pEdgeIndexs                          离散边的点索引(两个顶点在pEdgePoints中的索引，构成一个线段)
        /// \param std::vector<int> * pFaceToTriangleNum                   每个面对应离散后的三角面片数，面的顺序与体中面的顺序一致
        /// \param std::vector<int> * pEdgeToLineNum                       每条边对应离散后的线段数，边的顺序与体中边的顺序一致
        /// \param DiscreteEpsilonType deType                            几何离散的容差给定方式
        /// \return bool 成功返回true，失败返回false
        virtual bool DiscretizeWithIndices(
            const IBody *pGmIBody,
            double dDistanceEpsilon,
            double dAngleEpsilon,
            std::vector<Vector3d> &points,
            std::vector<Vector3d> &normals,
            std::vector<int> &triangleIndexs,
            std::vector<Vector2d> *pParameterUVs,
            std::vector<Vector3d> *pEdgePoints,
            std::vector<int> *pEdgeIndexs,
            std::vector<int> *pFaceToTriangleNum,
            std::vector<int> *pEdgeToLineNum,
            DiscreteEpsilonType deType) const = 0;

        /// \brief  把二维多段线离散成二维点集
        /// 
        /// \param  pGmIPolyCurve                二维多段线几何
        /// \param  dDistanceEpsilon             距离精度
        /// \param  dAngleEpsilon                角度精度
        /// \param  discretePoints               离散成的点集
        /// \return 成功返回true，失败返回false
        virtual bool Discretize(const IPolyCurve* pGmIPolyCurve, double dDistanceEpsilon, double dAngleEpsilon, std::vector<Vector2d> &discretePoints) const = 0;

        /// \brief  把三维多段线离散成三维点集
        /// 
        /// \param  pGmIPolyCurve3d              三维多段线几何
        /// \param  dDistanceEpsilon             距离精度
        /// \param  dAngleEpsilon                角度精度
        /// \param  discretePoints               离散成的点集
        /// \return 成功返回true，失败返回false
        virtual bool Discretize(const IPolyCurve3d* pGmIPolyCurve3d, double dDistanceEpsilon, double dAngleEpsilon, std::vector<Vector3d>& discretePoints) const = 0;

        /// \brief  把体离散成索引形式的三角面片(带索引)
        /// \param  const IBody *pGmIBody                                  体
        /// \param  double dDistanceEpsilon                                距离精度
        /// \param  double dAngleEpsilon                                   角度精度
        /// \param std::vector<Vector3d> &points                           离散成的点集
        /// \param std::vector<Vector3d> &normals                          在原来曲面上的法向
        /// \param std::vector<int> &triangleIndexs                        三角面片链表（存三个顶点在pointList中的索引，每三个索引构成一个三角形）
        /// \param std::vector<Vector2d> * pParameterUVs                   离散点在原来曲面上的参数,当输入为 nullptr 时不输出
        /// \param std::vector<Vector3d> * pEdgePoints                     离散边的点集
        /// \param std::vector<int> * pEdgeIndexs                          离散边的点索引(两个顶点在pEdgePoints中的索引，构成一个线段)
        /// \return bool 成功返回true，失败返回false
        GCMP_OBSOLETE_API(2021/01/01, Discretize(const IBody *, double, double, std::vector<Vector3d>&, std::vector<Vector3d>&, std::vector<int>&, std::vector<Vector2d>*, std::vector<Vector3d>*, std::vector<int>*, std::vector<int>*, std::vector<int>*)) virtual bool Discretize(const IBody *pGmIBody, double dDistanceEpsilon, double dAngleEpsilon, std::vector<Vector3d> &points, std::vector<Vector3d> &normals, std::vector<int> &triangleIndexs, std::vector<Vector2d>* pParameterUVs, std::vector<Vector3d> *pEdgePoints, std::vector<int> *pEdgeIndexs, DiscreteEpsilonType deType) const = 0;
    };
}